home *** CD-ROM | disk | FTP | other *** search
/ 130 MIDI Tool Box / 130 MIDI Tool Box.iso / drum / drumdll.c < prev    next >
C/C++ Source or Header  |  1992-02-14  |  5KB  |  169 lines

  1. /*------------------------------------------
  2.    DRUMDLL.C -- DLL module for DRUM program
  3.               (c) Charles Petzold,  1992
  4.   ------------------------------------------*/
  5.  
  6. #include <windows.h>
  7. extern "C" {
  8. #include <mmsystem.h>
  9. }
  10. #include <string.h>
  11. #include "drumdll.h"
  12.  
  13. #define min(a,b)      (((a) < (b)) ? (a) : (b))
  14. #define max(a,b)      (((a) > (b)) ? (a) : (b))
  15. #define minmax(a,x,b) (min (max (x, a), b))
  16.  
  17. #define TIMER_RES   5
  18.  
  19. void FAR PASCAL _export DrumTimerFunc (WORD, WORD, DWORD, DWORD, DWORD) ;
  20.  
  21. BOOL     bSequenceGoing, bEndSequence ;
  22. DRUM     drum ;
  23. HMIDIOUT hMidiOut ;
  24. HWND     hwndNotify ;
  25. int      iIndex ;
  26. WORD     wTimerRes, wTimerID ;
  27.  
  28. int FAR PASCAL LibMain (HANDLE hInstance, WORD wDataSeg, WORD wHeapSize,
  29.                         LPSTR lpszCmdLine)
  30.      {
  31.      return 1 ;
  32.      }
  33.  
  34. DWORD MidiOutMessage (HMIDIOUT hMidi, int iStatus, int iChannel,
  35.                                       int iData1,  int iData2)
  36.      {
  37.      DWORD dwMessage ;
  38.  
  39.      dwMessage = iStatus | iChannel | (iData1 << 8) | ((long) iData2 << 16) ;
  40.  
  41.      return midiOutShortMsg (hMidi, dwMessage) ;
  42.      }
  43.  
  44. void FAR PASCAL _export DrumSetParams (PDRUM pdrum)
  45.      {
  46.      _fmemcpy (&drum, pdrum, sizeof (DRUM)) ;
  47.      }
  48.  
  49. BOOL FAR PASCAL _export DrumBeginSequence (HWND hwnd)
  50.      {
  51.      TIMECAPS tc ;
  52.  
  53.      hwndNotify = hwnd ;           // Save window handle for notification
  54.      DrumEndSequence (TRUE) ;      // Stop current sequence if running
  55.  
  56.                // Open the MIDI Mapper output port
  57.  
  58.      if (midiOutOpen (&hMidiOut, (WORD) MIDIMAPPER, NULL, NULL, 0L))
  59.           return FALSE ;
  60.  
  61.                // Send Program Change messages for channels 9 and 15
  62.  
  63.      MidiOutMessage (hMidiOut, 0xC0,  9, 0, 0) ;
  64.      MidiOutMessage (hMidiOut, 0xC0, 15, 0, 0) ;
  65.  
  66.                // Begin sequence by setting a timer event
  67.  
  68.      timeGetDevCaps (&tc, sizeof (TIMECAPS)) ;
  69.      wTimerRes = minmax (tc.wPeriodMin, TIMER_RES, tc.wPeriodMax) ;
  70.      timeBeginPeriod (wTimerRes) ;
  71.  
  72.      wTimerID = timeSetEvent (max ((int) wTimerRes, drum.iMsecPerBeat),
  73.                               wTimerRes, DrumTimerFunc, 0L, TIME_ONESHOT) ;
  74.  
  75.      if (wTimerID == 0)
  76.           {
  77.           timeEndPeriod (wTimerRes) ;
  78.           midiOutClose (hMidiOut) ;
  79.           return FALSE ;
  80.           }
  81.  
  82.      iIndex = -1 ;
  83.      bEndSequence = FALSE ;
  84.      bSequenceGoing = TRUE ;
  85.  
  86.      return TRUE ;
  87.      }
  88.  
  89. void FAR PASCAL _export DrumEndSequence (BOOL bRightAway)
  90.      {
  91.      if (bRightAway)
  92.           {
  93.           if (bSequenceGoing)
  94.                {
  95.                                                   // stop the timer
  96.                if (wTimerID)
  97.                     timeKillEvent (wTimerID) ;
  98.                timeEndPeriod (wTimerRes) ;
  99.                                                   // turn off all notes
  100.  
  101.                MidiOutMessage (hMidiOut, 0xB0,  9, 123, 0) ;
  102.                MidiOutMessage (hMidiOut, 0xB0, 15, 123, 0) ;
  103.  
  104.                                                   // close the MIDI port
  105.                midiOutClose (hMidiOut) ;
  106.                bSequenceGoing = FALSE ;
  107.                }
  108.           }
  109.      else
  110.           bEndSequence = TRUE ;
  111.      }
  112.  
  113. void FAR PASCAL _export DrumTimerFunc (WORD  wID, WORD  wMsg, DWORD dwUser,
  114.                                        DWORD dw1, DWORD dw2)
  115.      {
  116.      static DWORD dwSeqExtLast [NUM_PERC], dwSeqBasLast [NUM_PERC] ;
  117.      int          i ;
  118.  
  119.                // Note Off messages for channels 9 and 15
  120.  
  121.      if (iIndex != -1)
  122.           {
  123.           for (i = 0 ; i < NUM_PERC ; i++)
  124.                {
  125.                if (dwSeqExtLast[i] & 1L << iIndex)
  126.                     MidiOutMessage (hMidiOut, 0x80,  9, i + 35, 0) ;
  127.  
  128.                if (dwSeqBasLast[i] & 1L << iIndex) ;
  129.                     MidiOutMessage (hMidiOut, 0x80, 15, i + 35, 0) ;
  130.                }
  131.           }
  132.  
  133.                // Increment index and notify window to advance bouncing ball
  134.  
  135.      iIndex = (iIndex + 1) % drum.iNumBeats ;
  136.      PostMessage (hwndNotify, WM_USER_NOTIFY, iIndex, timeGetTime ()) ;
  137.  
  138.                // Check if ending the sequence
  139.  
  140.      if (bEndSequence && iIndex == 0)
  141.           {
  142.           PostMessage (hwndNotify, WM_USER_FINISHED, 0, 0L) ;
  143.           return ;
  144.           }
  145.  
  146.                // Note On messages for channels 9 and 15
  147.  
  148.      for (i = 0 ; i < NUM_PERC ; i++)
  149.           {
  150.           if (drum.dwSeqExt[i] & 1L << iIndex)
  151.                MidiOutMessage (hMidiOut, 0x90,  9, i + 35, drum.iVelocity) ;
  152.  
  153.           if (drum.dwSeqBas[i] & 1L << iIndex)
  154.                MidiOutMessage (hMidiOut, 0x90, 15, i + 35, drum.iVelocity) ;
  155.  
  156.           dwSeqExtLast[i] = drum.dwSeqExt[i] ;
  157.           dwSeqBasLast[i] = drum.dwSeqBas[i] ;
  158.           }
  159.                // Set a new timer event
  160.  
  161.      wTimerID = timeSetEvent (max ((int) wTimerRes, drum.iMsecPerBeat),
  162.                               wTimerRes, DrumTimerFunc, 0L, TIME_ONESHOT) ;
  163.  
  164.      if (wTimerID == 0)
  165.           {
  166.           PostMessage (hwndNotify, WM_USER_ERROR, 0, 0L) ;
  167.           }
  168.      }
  169.